#include <iostream>
#include "logtxt.hpp"
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <sys/wait.h>
#include <pthread.h>
#include "ThreadPool.hpp"
#include <signal.h>
#include "Guard.hpp"
using namespace std;
extern Log lg;
enum
{
    SOCKET_ERR = 1,
    BIND_ERR,
    LISTEN_ERR
};
const int backlog = 10;

class ThreadDate
{
public:
    int sockfd_;
    uint16_t port_;
    string ip_;

public:
    ThreadDate(int sockfd, const string &ip, const uint16_t port) : sockfd_(sockfd), port_(port), ip_(ip)
    {
    }
};
class TcpServer
{
private:
    uint16_t port_;
    string ip_;
    int listensockfd_;

public:
    TcpServer(const uint16_t &port, const string &ip = "0.0.0.0") : port_(port), ip_(ip)
    {
    }
    void Init()
    {
        listensockfd_ = socket(AF_INET, SOCK_STREAM, 0);
        // cout << listensockfd_ << endl;
        if (listensockfd_ < 0)
        {
            lg(fatal, "socket fail,erron:%d,strerror:%s", errno, strerror(errno));
            exit(SOCKET_ERR);
        }
        lg(Info, "socket success,erron:%d,strerror:%s", errno, strerror(errno));

        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        inet_aton(ip_.c_str(), &server.sin_addr);
        server.sin_port = htons(port_);

        socklen_t len = sizeof(server);
        int n = bind(listensockfd_, (const sockaddr *)&server, len);
        if (n < 0)
        {
            lg(fatal, "bind fail,erron:%d,strerror:%s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(Info, "bind success,erron:%d,strerror:%s", errno, strerror(errno));
        if (listen(listensockfd_, backlog) < 0) // 将主动文件描述符转化为被动描述符，监听连接请求
        {
            lg(fatal, "listen error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(LISTEN_ERR);
        }

        lg(Info, "listen socket success, listensock_: %d", listensockfd_);
    }

    // static void *Routine(void *args) // 设置为静态的原因是因为成员函数默认带了一个this参数
    // {
    //     pthread_detach(pthread_self());
    //     char buffer[1024];
    //     ThreadDate *th = static_cast<ThreadDate *>(args);
    //     while (true)
    //     {
    //         ssize_t s = read(th->sockfd_, buffer, sizeof(buffer));
    //         if (s > 0)
    //         {
    //             buffer[s] = 0;
    //             cout << "get a client message:" << buffer << endl;
    //             string message = "server sendto message:";
    //             message += buffer;
    //             write(th->sockfd_, message.c_str(), message.size());
    //         }
    //         else if (s == 0)
    //         {
    //             lg(Info, "%s%d is quit,server close socket:%d", th->ip_.c_str(), th->port_, th->sockfd_);
    //             break;
    //         }
    //         else
    //         {
    //             cerr << "read fail" << endl;
    //             break;
    //         }
    //     }
    //     delete th;
    // }

    void start()
    {
        // signal(SIGPIPE, SIG_IGN);

        Daemon();

        ThreadPool<Task>::GetInterface()->Start();

        while (true)
        {
            struct sockaddr_in client;
            memset(&client, 0, sizeof(client));
            socklen_t len = sizeof(client);

            // 接受连接
            int sockfd = accept(listensockfd_, (struct sockaddr *)&client, &len);

            if (sockfd < 0)
            {
                lg(Warning, "accept error, errno: %d, errstring: %s", errno, strerror(errno));
                continue;
            }

            char buffer[32];
            uint16_t clientport = ntohs(client.sin_port);
            string clientip = inet_ntop(AF_INET, &(client.sin_addr), buffer, sizeof(buffer));
            lg(Info, "get a new link.....,sockfd:%d,clientip:%s,clientport:%d", sockfd, clientip.c_str(), clientport);

            //----单进程版
            // Services(sockfd, clientip, clientport);
            // close(sockfd);

            // 多进程版
            // pid_t pid;
            // pid = fork();
            // if (pid == 0)
            // {
            //     // child
            //     close(listensockfd_);
            //     if (fork() > 0)
            //     {
            //         exit(0); // 孩子进程退出，孙子进程由系统回收
            //     }
            //     Services(sockfd, clientip, clientport);
            //     close(sockfd);
            //     exit(0);
            // }

            // // father
            // close(sockfd); // 父进程关闭sockfd并不会关闭文件，因为进程创建会对父进程的文件描述符表中相应的文件引用计数++
            // int ret = waitpid(pid, NULL, 0);

            // 多线程版

            // pthread_t tid;
            // ThreadDate *th = new ThreadDate(sockfd, clientip, clientport);
            // pthread_create(&tid, NULL, Routine, th);

            // 线程池版
            Task t(sockfd, clientip, clientport);
            ThreadPool<Task>::GetInterface()->push(t);
        }
    }

    void Services(int sockfd, const string &clientip, const uint16_t &clientport)
    {
        while (true)
        {
            char buffermessage[1024];
            ssize_t s = read(sockfd, buffermessage, sizeof(buffermessage));
            if (s > 0)
            {
                buffermessage[s] = 0;
                cout << "get a client message:" << buffermessage << endl;
                string message = "server sendto message:";
                message += buffermessage;
                write(sockfd, message.c_str(), message.size());
            }
            else if (s == 0)
            {
                lg(Info, "%s%d is quit,server close socket:%d", clientip.c_str(), clientport, sockfd);
                break;
            }
            else
            {
                cerr << "read fail" << endl;
                break;
            }
        }
    }
    ~TcpServer()
    {
        close(listensockfd_);
    }
};
